import math
import numpy as np

PEMA6 = 0.29
PEMA18 = 0.11
PEMA54 = 0.04

VEMA5 = 0.33
VEMA15 = 0.13
VEMA45 = 0.04

# SMA周期
WeightPeriods = 15
SegmentCount = 3

# Candle周期
WeightPeriodsCandle = 15
SegmentCountCandle = 2

def ema(alpha, last_ema, close):
    ema_val = close
    if last_ema != 0 and last_ema != None:
        ema_val = close * alpha + last_ema * (1 - alpha)
    return ema_val


def ema6(last_ema, close):
    return ema(PEMA6, last_ema, close)


def ema18(last_ema, close):
    return ema(PEMA18, last_ema, close)


def ema54(last_ema, close):
    return ema(PEMA54, last_ema, close)


def vema5(last_ema, val):
    return ema(VEMA5, last_ema, val)


def vema15(last_ema, val):
    return ema(VEMA15, last_ema, val)


def vema45(last_ema, val):
    return ema(VEMA45, last_ema, val)


def close(close, ema):
    val = (close - ema) / close * 100
    return val


def angle_ema(today_val,yesterday_val):
    if yesterday_val == 0:
        return 0
    val = math.atan(((today_val / yesterday_val)-1) * 100) * 180 / math.pi
    return val

def pipsort(l):
    """
    默认降序排列
    :param l:
    :return:
    """
    result = []
    for i in range(len(l)):
        n = sorted(l, reverse=True).index(l[i]) + 1
        result.append(n)
    return result


def calSignature(v1, v2, v3, valuePool):
    """
    计算Signature
    :param v1: 第一个值
    :param v2: 第二个值
    :param v3: 第三个值
    :param valuePool: 存放过去值的列表
    :return:
    """
    price_range = np.average([abs(v1), abs(v2), abs(v3)])

    if len(valuePool) >= WeightPeriods:
        valuePool.pop(0)
    if price_range == 0:
        return None
    valuePool.append(price_range)
    sma_15_of_price_range = np.average(valuePool)
    range_multiplie = price_range / sma_15_of_price_range
    capped_range_multiplier = range_multiplie
    if range_multiplie >= 1:
        capped_range_multiplier = 1
    factor = 1 / (price_range / 100) * capped_range_multiplier / (100 / SegmentCount)
    ema6 = int(round(v1 * factor, 0))
    ema18 = int(round(v2 * factor, 0))
    ema54 = int(round(v3 * factor, 0))
    return "{}_{}_{}".format(ema6,ema18,ema54)


def calCandleSignature(open_price,high_price,low_price,close_price,candleRangePool):
    if high_price == low_price :
        return "0_0_0"
    candle_range = (high_price - low_price) / 3
    if len(candleRangePool) >= WeightPeriods:
        candleRangePool.pop(0)
    candleRangePool.append(candle_range)
    sma_15_of_candle_range = np.average(candleRangePool)
    candle_range_multiplier = candle_range / sma_15_of_candle_range
    capped_range_multiplier = candle_range_multiplier
    if capped_range_multiplier >= 1:
        capped_range_multiplier = 1
    # print(candle_range, capped_range_multiplier, SegmentCountCandle,high_price,low_price)
    factor = 1 / (candle_range/100)*capped_range_multiplier/(100/SegmentCountCandle)

    HO_Range = high_price - max(open_price,close_price)
    ho_1 = int(round(factor * HO_Range,0))
    HC_Range = open_price - close_price
    ho_2 = int(round(factor * HC_Range, 0))
    OL_Range = min(open_price,close_price) - low_price
    ho_3 = int(round(factor * OL_Range, 0))
    return "{}_{}_{}".format(ho_1,ho_2,ho_3)


def calCandleStatusSignature(i,csv_data,open_price,high_price,close_price,candleStatusRangePool):
    # print(i)
    if i - 1 > 0:
        datas = csv_data[i - 1].split(',')
        last_high_price = float(datas[2])
        last_close_price = float(datas[4])
        last_open_price = float(datas[1])
        totle_list = [last_high_price, last_close_price, high_price, close_price]
        candle_status_average = np.average(totle_list)
        candle_status_range = (max(totle_list) - min(totle_list)) / 2

        if len(candleStatusRangePool) >= WeightPeriodsCandle:
            candleStatusRangePool.pop(0)
        candleStatusRangePool.append(candle_status_range)
        sma_candle_status = np.average(candleStatusRangePool)
        candle_status_range_multiplier = candle_status_range / sma_candle_status
        if candle_status_range_multiplier > 1:
            candle_status_range_multiplier = 1
        candle_status_factor = 1 / (candle_status_range / 100) * candle_status_range_multiplier / (100 / SegmentCountCandle)

        TO_Range = open_price - min(totle_list)
        TO = int(round(candle_status_factor * TO_Range,0))

        YO_RANGE = last_open_price - min(totle_list)
        YO = int(round(candle_status_factor * YO_RANGE,0))

        YC_RANGE = last_close_price - min(totle_list)
        YC = int(round(candle_status_factor * YC_RANGE,0))

        return "{}_{}_{}".format(TO,YO,YC)

def calCandleMSignature(i, csv_data, today_open_price, today_high_price, today_low_price, today_close_price, Pool):

    if i - 2 > 0:
        # 昨天
        yest_datas = csv_data[i - 1].split(',')
        yest_high_price = float(yest_datas[2])
        yest_low_price = float(yest_datas[3])
        yest_close_price = float(yest_datas[4])
        yest_open_price = float(yest_datas[1])

        # 前天
        befor_yest_datas = csv_data[i - 2].split(',')
        befor_yest_high_price = float(befor_yest_datas[2])
        befor_yest_low_price = float(befor_yest_datas[3])
        befor_yest_close_price = float(befor_yest_datas[4])
        befor_yest_open_price = float(befor_yest_datas[1])

        s1 = (today_high_price + today_low_price) / 2
        s2 = (yest_high_price + yest_low_price) / 2
        s3 = (befor_yest_high_price + befor_yest_low_price) /2
        s = max(s1,s2,s3) - min(today_low_price,yest_low_price,befor_yest_low_price)
        candle_range = s / 3

        if len(Pool) >= WeightPeriodsCandle:
            Pool.pop(0)
        Pool.append(candle_range)

        sma15 = np.average(Pool)*2
        range_multiplier = candle_range / sma15
        capped_range_multiplier = range_multiplier
        if capped_range_multiplier >= 1:
            capped_range_multiplier = 1
        factor = 1/(candle_range/100)*capped_range_multiplier/(100/SegmentCountCandle)

        T_Range = (today_open_price + today_close_price)/2 - min(today_low_price,yest_low_price,befor_yest_low_price)
        T = int(round(T_Range*factor,0))

        Y_Range = (yest_open_price + yest_close_price)/2 - min(today_low_price,yest_low_price,befor_yest_low_price)
        Y = int(round(Y_Range * factor, 0))

        Z_Range = (befor_yest_open_price + befor_yest_close_price) / 2 - min(today_low_price, yest_low_price, befor_yest_low_price)
        Z = int(round(Z_Range * factor, 0))

        # 明日收盘价格
        TO = None
        if i + 1 < len(csv_data):
            tomorrow_close = csv_data[i + 1].split(',')[4]
            TO_Range = float(tomorrow_close) - today_close_price
            TO = int(round(TO_Range * factor, 0))
        return "{}_{}_{}({})".format(T,Y,Z,TO)
    else:
        return "0_0_0"


